<?php
namespace services\payment;

use think\Request;
use Carbon\Carbon;
use think\Config;
use services\PaymentInterface;
use EasyWeChat\Foundation\Application;
use EasyWeChat\Payment\Order;
use \think\Exception;

/**
 * 微信支付
 */
class WxPay implements PaymentInterface
{
    private $app       = '';
    const BODY         = '双辉旅程网';
    const NOTIFY_URL   = 'http://wx.shsytour.cn/wxpay/notify.html';
    protected $options = [
            /**
             * Debug 模式，bool 值：true/false
             *
             * 当值为 false 时，所有的日志都不会记录
             */
            'debug'  => false,
            /**
             * 账号基本信息，请从微信公众平台/开放平台获取
             */
            'app_id'  => 'wx5a1090e16a2f3e95',         // AppID
            'secret'  => '7d7f576e91c8e8dc1af4fbeb6938ac2a',     // AppSecret
            'token'   => 'i9ch3f2ca',          // Token
            'aes_key' => 'RBuTcKRnHXbrLr4mrjQJW16ezM0UlggeHJZfu09ecnf',                    // EncodingAESKey，安全模式下请一定要填写！！！
            /**
             * 微信支付
             */
            'payment' => [
                'merchant_id'        => '1419891902',
                'key'                => '845d5f1153c27beed29f479640445148',
                'cert_path'          => 'path/to/your/cert.pem', // XXX: 绝对路径！！！！
                'key_path'           => 'path/to/your/key',      // XXX: 绝对路径！！！！
                // 'device_info'     => '013467007045764',
                // 'sub_app_id'      => '',
                // 'sub_merchant_id' => '',
                // ...
            ],
            /**
             * Guzzle 全局设置
             *
             * 更多请参考： http://docs.guzzlephp.org/en/latest/request-options.html
             */
            'guzzle' => [
                'timeout' => 3.0, // 超时时间（秒）
                'verify' => false, // 关掉 SSL 认证（强烈不建议！！！）
            ],
        ];

    public function __construct($options = [])
    {   
        $this->app = new Application(array_merge($this->options, $options));
    }
    /**
     * 统一下单
     * @param  [type] $attributes [description]
     * @return [type]               [description]
     */
    public function pay($attributes)
    {
        $res        = ['code' => 200, 'data' => ''];
        $payment    = $this->app->payment;
        $attributes = array_merge($attributes, [
                    'trade_type'   => 'NATIVE',
                    'notify_url'   => self::NOTIFY_URL
                ]);

        $order   = new Order($attributes);
        $result  = $payment->prepare($order);
        
        if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
            $prepayId = $result->prepay_id;
            switch ($result->trade_type) {
                case 'NATIVE':
                    $res['data'] = $result->code_url;
                    break;
                case 'JSAPI':
                    $res['data'] =  $payment->configForJSSDKPayment($prepayId);
                    break;
                case 'APP':
                    $res['data'] = $payment->configForAppPayment($prepayId);
                    break;
                default:
                    $res['data'] = $result;
                    break;
            }
            return $res;
        }else {
            throw new Exception($result->err_code, -9876); 
        }
    }
    /**
     * 查询订单
     * @param  [type] $order_no [description]
     * @param  string $type     [description]
     * @return [type]           [description]
     */
    public function queryOrder($order_no, $type = 'out_trade_no')
    {
        $payment = $this->app->payment;
        if ($type == 'out_trade_no') {
            return $payment->query($order_no);
        }elseif ($type == 'transaction_id') {
            return $payment->queryByTransactionId($order_no);
        }
        return false;
    }
    /**
     * 撤销订单
     * @param  [type] $order_no 订单号
     * @param  string $type     out_trade_no 内部订单号 | transaction_id 微信订单号
     * @return [type]           [description]
     */
    public function reverseOrder($order_no, $type = 'out_trade_no')
    {
        if ($type == 'out_trade_no') {
            return $payment->reverse($order_no);
        }elseif ($type == 'transaction_id') {
            return $payment->reverseByTransactionId($order_no);
        }
        return false;
    }
    /**
     * 关闭订单
     * @param  [type] $order_no [description]
     * @return [type]           [description]
     */
    public function closeOrder($order_no)
    {
        $payment = $this->app->payment;
        $payment->close($order_no);
    }
    /**
     * 下载对账单
     * @param  [type] $date [description]
     * @param  string $type [description]
     * ALL：返回当日所有订单信息（默认值）
     * SUCCESS：返回当日成功支付的订单
     * REFUND：返回当日退款订单
     * REVOKED：已撤销的订单
     * @return [type]       [description]
     */     
    public function downloadBill($date, $type = 'ALL')
    {
        $bill = $payment->downloadBill($date, 'SUCCESS'); // type: SUCCESS
        // bill 为 csv 格式的内容
        // 保存为文件
        file_put_contents('YOUR/PATH/TO/bill-20140603.csv', $bill);
    }
    /**
     * 退款
     * @param  [type] $out_trade_no [description]
     * @param  [type] $total_fee    [description]
     * @param  [type] $refund_fee   [description]
     * @return [type]               [description]
     */
    public function refund($out_trade_no, $total_fee, $refund_fee)
    {
        return ;
    }
    /**
     * 支付结果通知
     * @return [type] [description]
     */
    public function notify()
    {
        $response = $this->app->payment->handleNotify(function($notify, $successful){
            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
            if ($notify->attach == 'order') {
                $order = model('Orders')->getOrderInfo(['number' => $notify->out_trade_no]);
            }elseif ($notify->attach == 'recharge') {
                $order = model('Intergrateadds')->getOrderInfo(['order_num' => $notify->out_trade_no]);
            }
            if (!$order) { // 如果订单不存在
                return 'Order not exist.'; // 告诉微信，我已经处理完了，订单没找到，别再通知我了
            }

            // 如果订单存在
            // 检查订单是否已经更新过支付状态
            if ($order->paid_at) { // 假设订单字段“支付时间”不为空代表已经支付
                return true; // 已经支付成功了就不再更新了
            }
            // 用户是否支付成功
            if ($successful) {
                // 不是已经支付状态则修改为已经支付状态
                return $order->completeOrderPay($notify->out_trade_no);
            } else { // 用户支付失败
                $order->status = -1;
            }
            $order->save(); // 保存订单
            return true; // 返回处理完成
        });
        $response->send();
        return ;
    }
}
